#include "sem.h"

int SEM_InitFunc(void)
{
    char path[64];

	SEM_devcfg_Func();
	usleep(5000);

    memset(path, 0, sizeof(path));
    snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d", GPIO_SEM_CTRL);
    if (-1 == access(path, F_OK))
    {
        gpio_export(GPIO_SEM_CTRL);
        gpio_direction(GPIO_SEM_CTRL,GPIO_DIR_OUT);
        usleep(5000);
    }
	gpio_write(GPIO_SEM_CTRL,1);
	SEM_InitGpio();
	return 0;
}

int SEM_devcfg_Func(void)
{
	int hdl = -1;
	int ret =0;
	uint32_t ReadVal = 0;
	uint32_t tmp = 0;
	void *semAddr = NULL;

	semAddr = devm_map(0xF8007000,0x4,&hdl);
	if(semAddr == NULL)
	{
		printf("eccAddr NULL...ERROR...\n\r");
		return -1;
	}

	ReadVal =(uint32_t) *((uint32_t *)semAddr);
	printf("start SEM_devcfg_Func semAddr DATA:0x%x...\n\r",ReadVal);

	tmp = ReadVal&(~(1<<27));

	*((uint32_t *)semAddr) = tmp;

	devm_unmap(semAddr, 0x4, &hdl);
	return ret;
}

int gpio_export(int pin)
{
    char buffer[64];
    int len;
    int fd;

    fd = open("/sys/class/gpio/export", O_WRONLY);
    if (fd < 0)
    {
        printf("Failed to open export for writing!\n");
        return (-1);
    }

    memset(buffer, 0, sizeof(buffer));
    len = snprintf(buffer, sizeof(buffer), "%d", pin);
    if (write(fd, buffer, len) < 0)
    {
        printf("Failed to export gpio=%d!\n", pin);
        close(fd);
        return -1;
    }

    close(fd);
    return 0;
}

int gpio_direction(int pin, int dir)
{
    static const char dir_str[] = "in\0out";
    char path[64];
    int fd;

    snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/direction", pin);
    fd = open(path, O_WRONLY);
    if (fd < 0)
    {
        printf("Failed to open gpio direction for writing!\n");
        return -1;
    }

    if (write(fd, &dir_str[dir == 0 ? 0 : 3], dir == 0 ? 2 : 3) < 0)
    {
        printf("Failed to set direction!\n");
        close(fd);
        return -1;
    }

    close(fd);
    return 0;
}

int gpio_write(int pin, int value)
{
    char path[64];
    int fd;

    snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/value", pin);
    fd = open(path, O_WRONLY);
    if (fd < 0)
    {
        printf("Failed to open gpio=%d value for writing!\n", pin);
        return -1;
    }
#if 0
    static const char values_str[] = "01";
	if (write(fd, &values_str[value == 0 ? 0 : 1], 1) < 0)
	{
        printf("Failed to write gpio=%d value=%d!\n", pin, value);
        close(fd);
        return -1;
    }
#else
    if (value == 0x1)
    {
        write(fd, "1", 2);
    }
    else if (value == 0x0)
    {
        write(fd, "0", 2);
    }
    else
    {
    }
#endif

    close(fd);
    return 0;
}

int SEM_InitGpio(void)
{
    char path[64];

	memset(path, 0, sizeof(path));
	snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d", PL_GPO_SEM+26);
	if (-1 == access(path, F_OK))
	{
		gpio_export(PL_GPO_SEM+26);
		gpio_direction(PL_GPO_SEM+26,GPIO_DIR_IN);
		usleep(5000);
	}

	memset(path, 0, sizeof(path));
	snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d", PL_GPO_SEM+30);
	if (-1 == access(path, F_OK))
	{
		gpio_export(PL_GPO_SEM+30);
		gpio_direction(PL_GPO_SEM+30,GPIO_DIR_IN);
		usleep(5000);
	}
	return 0;
}

int SEM_CheckStateFunc(void)
{
	int hdl = -1;
	int tmp = 0;
	int state = 0;
	void *cntAddr = NULL;

	state = SEM_readGpio();
	printf("SEM_CheckStateFunc state:0x%x...\n\r",state);

	cntAddr = devm_map(0x43c00030,0x4,&hdl);
	if(cntAddr == NULL)
	{
		printf("cntAddr NULL...ERROR...\n\r");
		return -1;
	}

	tmp =(uint32_t) *((uint32_t *)cntAddr);
	printf("SEM_CheckStateFunc count:0x%x...\n\r",tmp);
	devm_unmap(cntAddr, 0x4, &hdl);
	return tmp;
}

int SEM_readGpio(void)
{
	int val=0;
	int state=0;

	val = gpio_read(PL_GPO_SEM+26);
	printf("val:%d\n",val);
	val = val<<0;
	state = val|state;

	val = gpio_read(PL_GPO_SEM+30);
	printf("val:%d\n",val);
	val = val<<1;
	state = val|state;
	return state;
}

int gpio_read(int pin)
{
    char path[64];
    char value_str[3];
    int fd;

    snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/value", pin);
    fd = open(path, O_RDONLY);
    if (fd < 0)
    {
        printf("Failed to open gpio=%d value for reading!\n", pin);
        return -1;
    }

    if (read(fd, value_str, 3) < 0)
    {
        printf("Failed to read gpio=%d value!\n", pin);
        close(fd);
        return -1;
    }

    close(fd);
    return (atoi(value_str));
}

void *devm_map(unsigned long addr, int len, int *phandle)
{
    off_t offset;
    void *map_base;

    if ((*phandle = open("/dev/mem", O_RDWR | O_SYNC)) == -1)
    {
        printf("cannot open '/dev/mem'\n");
        goto err_open;
    }
    // printf("/dev/mem opened.\n");

    /*
     * Map it
     */

    /* offset for mmap() must be page aligned */
    offset = addr & ~(sysconf(_SC_PAGE_SIZE) - 1);

    map_base = mmap(NULL, len + addr - offset, PROT_READ | PROT_WRITE,
                    MAP_SHARED, *phandle, offset);
    if (map_base == MAP_FAILED)
    {
        printf("mmap failed\n");
        goto err_mmap;
    }
    // printf("Memory mapped at address %p.\n", map_base);

    return map_base + addr - offset;

err_mmap:
    close(*phandle);

err_open:
    return NULL;
}

void devm_unmap(void *virt_addr, int len, int *phandle)
{
    unsigned long addr;

    if (*phandle == -1)
    {
        printf("'/dev/mem' is closed\n");
        return;
    }

    /* page align */
    addr = (((unsigned long)virt_addr) & ~(sysconf(_SC_PAGE_SIZE) - 1));
    munmap((void *)addr, len + (unsigned long)virt_addr - addr);
    close(*phandle);
    *phandle = -1;
}

void sem_test_func(unsigned char id,char *writebuf,int len)
{
    int wr_static, w_static;
    static int sem_fd = -1;
    char readbuf[256];
    char *uart1 = "/dev/ttyS";
    char uartx[32];

    memset(readbuf, 0, sizeof(readbuf));
    memset(uartx, 0, sizeof(uartx));
    snprintf(uartx, sizeof(uartx), "%s%d", uart1, id);

    if (sem_fd < 0)
    {
    	sem_fd = open(uartx, O_RDWR | O_NOCTTY | O_NDELAY);
		if(sem_fd < 0)
		{
        	printf("open %s is failed.\n", uartx);
			return ;
		}
	    printf("open %s success.\n", uartx);
	    set_opt(sem_fd, 9600, 8, 'N', 1);
	    usleep(10000);
		SEM_InitFunc();
goto TXT;
    }

//      w_static = write(sem_fd, writebuf, sizeof(writebuf));
		w_static = write(sem_fd, writebuf, len);

      if (w_static > 0)
        {
                printf("uart id=%d send len is %d.\n", id, w_static);
        }
      else
        {
                printf("uart id=%d send failed, ret=%d.\n", id, w_static);
        }
TXT:
       wr_static = 0;
       usleep(500000);
       wr_static = read(sem_fd, readbuf, 256);
       if (wr_static > 0)
       {
          printf("uart id=%d recv len=%d, msg=", id, wr_static);
          for (int i = 0; i < wr_static; i++)
          {
              printf("%c", readbuf[i]);
              usleep(10);
          }
             printf("\n");

//		  printf("zifuchuan xianshi ruxia\n\r");
//		  printf("%s",readbuf);
       }
       else
       {
                //	sleep(1);
       }
}

int set_opt(int fd, int nSpeed, int nBits, char nEvent, int nStop)
{
    struct termios newtio, oldtio;
    /* 閼惧嘲褰噁d娑撴彃褰涚�电懓绨查惃鍓噀rmios缂佹挻鐎担鎿勭礉鏉╂瑦顒炴稉鏄忣洣閺勵垱鐓＄拠顫閸欙絾妲搁崥锕�鎯庨崝銊︻劀鐢拷 */
    if (tcgetattr(fd, &oldtio) != 0)
    {
        printf("SetupSerial 1");
        return -1;
    }
    // 濞撳懐鈹�
    bzero(&newtio, sizeof(newtio));
    newtio.c_cflag |= CLOCAL | CREAD; // 闁板秶鐤嗛幋鎰拱閸︾増膩瀵拷(閺堫剙婀存潻鐐村复閵嗕椒绗夐弨鐟板綁缁旑垰褰涢幍鈧張澶庘偓锟�)閵嗕礁褰茬拠锟�
    newtio.c_cflag &= ~CSIZE;         // 濞撳懐鈹栭弫鐗堝祦娴ｅ秷顔曠純锟�
    /* 闁瀚ㄩ弫鐗堝祦娴ｏ拷 */
    switch (nBits)
    {
    case 7:
        newtio.c_cflag |= CS7;
        break;
    case 8:
        newtio.c_cflag |= CS8;
        break;
    }
    /* 闁瀚ㄩ弽锟犵崣娴ｏ拷 */
    switch (nEvent)
    {
    case 'O':
        newtio.c_cflag |= PARENB;
        newtio.c_cflag |= PARODD;
        // newtio.c_iflag |= (INPCK | ISTRIP);	//閸氼垳鏁ゆ潏鎾冲弳婵傚洤浼撳Λ鈧ù瀣ㄢ偓浣稿箵閹哄顑囬崗顐＄秴
        newtio.c_iflag |= INPCK;
        break;
    case 'E':
        newtio.c_cflag |= PARENB;
        newtio.c_cflag &= ~PARODD;
        // newtio.c_iflag |= (INPCK | ISTRIP);
        newtio.c_iflag |= INPCK;
        break;
    case 'N':
        newtio.c_cflag &= ~PARENB;
        break;
    }
    /* 闁瀚ㄥ▔銏㈠閻滐拷 */
    switch (nSpeed)
    {
    case 2400:
        cfsetispeed(&newtio, B2400);
        cfsetospeed(&newtio, B2400);
        break;
    case 4800:
        cfsetispeed(&newtio, B4800);
        cfsetospeed(&newtio, B4800);
        break;
    case 9600:
        cfsetispeed(&newtio, B9600);
        cfsetospeed(&newtio, B9600);
        break;
    case 115200:
        cfsetispeed(&newtio, B115200);
        cfsetospeed(&newtio, B115200);
        break;
    case 230400:
        cfsetispeed(&newtio, B230400);
        cfsetospeed(&newtio, B230400);
        break;
    case 460800:
        cfsetispeed(&newtio, B460800);
        cfsetospeed(&newtio, B460800);
        break;
    case 921600:
        cfsetispeed(&newtio, B921600);
        cfsetospeed(&newtio, B921600);
        break;
    default:
        cfsetispeed(&newtio, B9600);
        cfsetospeed(&newtio, B9600);
        break;
    }
    /* 闁瀚ㄩ崑婊勵剾娴ｅ稄绱濈挩灞兼妧linux娑撳绗夐懗鍊燁啎缂冿拷(1.5 0.5)閸嬫粍顒涙担锟� */
    if (nStop == 1)
        newtio.c_cflag &= ~CSTOPB;
    else if (nStop == 2)
        newtio.c_cflag |= CSTOPB;
    newtio.c_cc[VTIME] = 0;
    newtio.c_cc[VMIN] = 0;
    tcflush(fd, TCIFLUSH);
    /* 鐠佸墽鐤嗛弬浼村帳缂冿拷 */
    if ((tcsetattr(fd, TCSANOW, &newtio)) != 0)
    {
        perror("com set error");
        return -1;
    }
    //	printf("set done!\n\r");
    return 0;
}


